package ac.il.technion.c236369.hw4.typehandlers.tsp;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;

import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.protocol.HTTP;
import org.apache.http.protocol.HttpContext;
import org.apache.log4j.Logger;

import ac.il.technion.c236369.hw4.configuration.ServerConfig;
import ac.il.technion.c236369.hw4.core.entity.EntityTemplate;
import ac.il.technion.c236369.hw4.core.producers.AccessDeniedContentProducer;
import ac.il.technion.c236369.hw4.core.producers.FileNotFoundContenProducer;
import ac.il.technion.c236369.hw4.typehandlers.TypeHandler;
import ac.il.technion.c236369.hw4.typehandlers.tsp.templates.producers.TSPContentProducer;

/**
 * @author Artem Barger, Maxim Aizenshtein
 *
 */
public class TSPEngine implements TypeHandler {

	private final Logger log = Logger.getLogger( TSPEngine.class);
	@Override
	public void handle( final HttpRequest request, final HttpResponse response,
			final HttpContext context) {
		final String uri = readResourceURI( request);
		log.info( "Requested tsp file with name: <" + uri + ">");
		Integer endFileName = uri.indexOf( "?");
		Boolean hasParameters = endFileName >=0;
		final Map<String, String> params = readParams( uri.substring( hasParameters?endFileName + 1:(uri.length())));
		try {
			File file = new File( ServerConfig.getInstance().getProperties().getBase( ),
						URLDecoder.decode(uri.substring(0, (hasParameters)?endFileName:uri.length( )), "UTF-8"));
			
	        File requestedFile = null;
	        if ( file.isDirectory( )) {
	        	String[] list = file.list();
	        	for ( String $ : list) {
	        		if ( ServerConfig.getInstance().getProperties().getWelcomeFiles( ).contains( $))
	        			requestedFile = new File( file, $);
	        	}
	        } 
	        if ( requestedFile == null)
	        	requestedFile = file;
			
			EntityTemplate body = null;
			if ( !requestedFile.exists( )) {
				body = new EntityTemplate( new FileNotFoundContenProducer( ));
				response.setStatusCode( HttpStatus.SC_NOT_FOUND);
				log.info( "No <" + uri + "> found");
			} else if ( requestedFile.isDirectory() || !requestedFile.canRead()) {
				body = new EntityTemplate( new AccessDeniedContentProducer( ));
				response.setStatusCode( HttpStatus.SC_FORBIDDEN);
				log.info( "Has no access or directory for <" + uri + ">.");
			} else {
				body = new EntityTemplate( new TSPContentProducer(requestedFile, params));
				response.setStatusCode( HttpStatus.SC_OK);
				log.info( "Request for <" + uri +"> has been succefully served.");
			}
			
			Map<String, String> mimeTypes = ServerConfig.getInstance().getProperties().getMimeTypes();
			if ( mimeTypes.containsKey( "tsp"))
				body.setContentType( mimeTypes.get("tsp"));
			else {
				body.setContentType( mimeTypes.get(ServerConfig.DEFAULT_MIME_TYPE));
				log.warn( "There is no mime type defined for tsp content files.");
			}
			response.setEntity( body);
		} catch (UnsupportedEncodingException e) {
			log.error(e);
		} catch (IllegalStateException e) {
			log.error(e);
		}
	}

	private String readResourceURI(HttpRequest request) {
		String uri = request.getRequestLine().getUri( );
		String host = "";
		if ( request.getHeaders( HTTP.TARGET_HOST) != null) {
			host = request.getHeaders( HTTP.TARGET_HOST)[0].getValue( );
		}
		if ( !uri.contains(host))
			return uri;
		return uri.substring( uri.indexOf(host) + host.length( ), uri.length( ));
	}

	private Map<String, String> readParams(String parameters) {
		StringTokenizer paramTokenizer = new StringTokenizer( parameters, "&");
		Map<String, String> $  = new HashMap<String, String>( );
		while ( paramTokenizer.hasMoreTokens( )) {
			String paramKeyValue = paramTokenizer.nextToken( );
			$.put( paramKeyValue.split("=")[0], paramKeyValue.split("=")[1]);
		}
		return $; 
	}

}
